/*
 * Copyright (C) 2016  Nicola Spanti (RyDroid) <dev@nicola-spanti.info>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */


#include <check.h>
#include "PlanetWars2dRT-core/specific/model/planet.h"


struct planet_t a_planet;

void
tests_setup_init(void)
{
  planet_init_first_time_only_default(&a_planet);
}

void
tests_setup_free(void)
{
  planet_destructor(&a_planet);
}


START_TEST(test_planet_radius)
{
  ck_assert(planet_set_radius(&a_planet,  1));
  ck_assert_uint_eq(planet_get_radius(&a_planet),  1);
  ck_assert(planet_set_radius(&a_planet, 20));
  ck_assert_uint_eq(planet_get_radius(&a_planet), 20);
  ck_assert(planet_set_radius(&a_planet, 25));
  ck_assert_uint_eq(planet_get_radius(&a_planet), 25);
  
  ck_assert(!planet_set_radius(&a_planet,  0));
  ck_assert_uint_ne(planet_get_radius(&a_planet),  0);
}
END_TEST

START_TEST(test_planet_diameter)
{
  ck_assert(planet_set_diameter(&a_planet,  2));
  ck_assert_uint_eq(planet_get_diameter(&a_planet),  2);
  ck_assert(planet_set_diameter(&a_planet, 25));
  ck_assert_uint_eq(planet_get_diameter(&a_planet), 25);
  
  ck_assert(!planet_set_diameter(&a_planet,  0));
  ck_assert_uint_ne(planet_get_diameter(&a_planet),  0);
  ck_assert(!planet_set_diameter(&a_planet,  1));
  ck_assert_uint_ne(planet_get_diameter(&a_planet),  1);
}
END_TEST

START_TEST(test_planet_top_left_position)
{
  planet_set_top_left_position_x(&a_planet, 0);
  ck_assert_uint_eq(planet_get_top_left_position_x(&a_planet), 0);
  planet_set_top_left_position_x(&a_planet, 25);
  ck_assert_uint_eq(planet_get_top_left_position_x(&a_planet), 25);
  
  planet_set_top_left_position_y(&a_planet, 0);
  ck_assert_uint_eq(planet_get_top_left_position_y(&a_planet), 0);
  planet_set_top_left_position_y(&a_planet, 25);
  ck_assert_uint_eq(planet_get_top_left_position_y(&a_planet), 25);

  position_2d_uint position;
  position.x = position.y = 0;
  planet_set_top_left_position(&a_planet, position);
  ck_assert_uint_eq(planet_get_top_left_position_x(&a_planet), 0);
  ck_assert_uint_eq(planet_get_top_left_position_y(&a_planet), 0);
  position.x = position.y = 25;
  planet_set_top_left_position(&a_planet, position);
  ck_assert_uint_eq(planet_get_top_left_position_x(&a_planet), 25);
  ck_assert_uint_eq(planet_get_top_left_position_y(&a_planet), 25);
}
END_TEST

START_TEST(test_planet_center_position)
{
  planet_set_radius(&a_planet, 20);
  
  planet_set_top_left_position_x(&a_planet, 0);
  ck_assert_uint_eq(planet_get_center_position_x(&a_planet),
		    planet_get_radius(&a_planet));
  planet_set_top_left_position_y(&a_planet, 0);
  ck_assert_uint_eq(planet_get_center_position_y(&a_planet),
		    planet_get_radius(&a_planet));
}
END_TEST

START_TEST(test_planet_life_max)
{
  ck_assert_uint_gt(planet_get_life_max(&a_planet), 0);
  ck_assert_uint_le(planet_get_life_current(&a_planet),
		    planet_get_life_max(&a_planet));
}
END_TEST

START_TEST(test_planet_reduce_life)
{
  unsigned int life = planet_get_life_current(&a_planet);
  planet_reduce_life(&a_planet, 1);
  if(life == 0)
    {
      ck_assert_uint_eq(planet_get_life_current(&a_planet), 0);
    }
  else
    {
      ck_assert_uint_eq(planet_get_life_current(&a_planet), --life);
    }
  ck_assert_uint_lt(planet_get_life_current(&a_planet),
		    planet_get_life_max(&a_planet));
  
  planet_reduce_life(&a_planet,
		     planet_get_life_current(&a_planet) +1);
  ck_assert_uint_eq(planet_get_life_current(&a_planet), 0);
  ck_assert_uint_lt(planet_get_life_current(&a_planet),
		    planet_get_life_max(&a_planet));
}
END_TEST


START_TEST(test_planet_equals)
{
  ck_assert(planet_equals_except_observers(&a_planet, &a_planet));
  
  planet_reduce_life(&a_planet, 1);
  ck_assert(planet_equals_except_observers(&a_planet, &a_planet));
  
  planet_reduce_life(&a_planet,
		     planet_get_life_current(&a_planet) +1);
  ck_assert(planet_equals_except_observers(&a_planet, &a_planet));
  
  struct planet_t planet1, planet2;
  planet1 = a_planet;
  planet2 = a_planet;
  
  planet_set_top_left_position_x(&planet1, 1);
  planet_set_top_left_position_x(&planet2, 2);
  ck_assert(!planet_equals_except_observers(&planet1, &planet2));
  planet_set_top_left_position_x(&planet1, 0);
  planet_set_top_left_position_x(&planet2, 0);
  
  ck_assert(planet_equals_except_observers(&planet1, &planet2));
  planet1.player_index = 1;
  planet2.player_index = 2;
  ck_assert(!planet_equals_except_observers(&planet1, &planet2));
  planet1.player_index = planet2.player_index;
  ck_assert(planet_equals_except_observers(&planet1, &planet2));
  
  planet_set_radius(&planet1, 10);
  planet_set_radius(&planet2, 20);
  ck_assert(!planet_equals_except_observers(&planet1, &planet2));
  planet_set_radius(&planet1, planet_get_radius(&planet2));
  ck_assert(planet_equals_except_observers(&planet1, &planet2));
  
  planet_set_width(&planet1, 10);
  planet_set_width(&planet2, 20);
  ck_assert(!planet_equals_except_observers(&planet1, &planet2));
  planet_set_width(&planet1, planet_get_width(&planet2));
  ck_assert(planet_equals_except_observers(&planet1, &planet2));
  
  planet_set_height(&planet1, 10);
  planet_set_height(&planet2, 20);
  ck_assert(!planet_equals_except_observers(&planet1, &planet2));
  planet_set_height(&planet1, planet_get_height(&planet2));
  ck_assert(planet_equals_except_observers(&planet1, &planet2));
  
  ck_assert(planet_equals_except_observers (NULL,      NULL));
  ck_assert(!planet_equals_except_observers(&a_planet, NULL));
  ck_assert(!planet_equals_except_observers(NULL,      &a_planet));
}
END_TEST


Suite*
planet_suite(void)
{
  Suite* s = suite_create("Planet");
  
  TCase* tc_planet_size = tcase_create("Size");
  tcase_add_checked_fixture(tc_planet_size,
			    tests_setup_init, tests_setup_free);
  tcase_add_test(tc_planet_size,
		 test_planet_radius);
  tcase_add_test(tc_planet_size,
		 test_planet_diameter);
  
  TCase* tc_planet_position = tcase_create("Position");
  tcase_add_checked_fixture(tc_planet_position,
			    tests_setup_init, tests_setup_free);
  tcase_add_test(tc_planet_position,
		 test_planet_top_left_position);
  tcase_add_test(tc_planet_position,
		 test_planet_center_position);
  suite_add_tcase(s, tc_planet_position);
  
  TCase* tc_planet_life = tcase_create("Life");
  tcase_add_checked_fixture(tc_planet_life,
			    tests_setup_init, tests_setup_free);
  tcase_add_test(tc_planet_life,
		 test_planet_life_max);
  tcase_add_test(tc_planet_life,
		 test_planet_reduce_life);
  suite_add_tcase(s, tc_planet_life);
  
  TCase* tc_planet_others = tcase_create("Others");
  tcase_add_checked_fixture(tc_planet_others,
			    tests_setup_init, tests_setup_free);
  tcase_add_test(tc_planet_others,
		 test_planet_equals);
  suite_add_tcase(s, tc_planet_others);
  
  return s;
}

int
main(void)
{
  size_t number_failed;
  Suite* s;
  SRunner* sr;
  
  s = planet_suite();
  sr = srunner_create(s);
  
  srunner_run_all(sr, CK_NORMAL);
  number_failed = srunner_ntests_failed(sr);
  srunner_free(sr);
  
  return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
